﻿using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.Caching;
using System.Web;
using System.Web.UI;
using System.Xml.Serialization;

namespace blackhouse.AspQuartzWrapper {
    public class QuartzStartModule : IHttpModule {

        #region Fields

        private HttpContext currentContext;
        private HttpServerUtility currentServer;
        private HttpRequest currentRequest;
        private static bool initialized;
        private string hostLeftPart;

        #endregion

        public void Dispose() {
            //ISchedulerFactory schedFact = new StdSchedulerFactory();
            //IScheduler sched = schedFact.GetScheduler();
            //if (sched.IsStarted)
            //    sched.Shutdown(true);
            //initialized = false;
        }

        public void Init(HttpApplication context) {
            context.BeginRequest += Application_BeginRequest;
            context.AcquireRequestState += app_AcquireRequestState;
        }

        protected void Application_BeginRequest(object sender, EventArgs e) {
            HttpApplication app = (HttpApplication)sender;


        }

        void app_AcquireRequestState(object sender, EventArgs e) {
            if (initialized) return;
            this.currentContext = HttpContext.Current;
            if (this.currentContext != null && this.currentContext.Handler is Page) {
                 
                this.currentServer = this.currentContext.Server;
                this.currentRequest = this.currentContext.Request;
                //this.hostLeftPart = ;
                this.hostLeftPart = this.currentRequest.Url.GetLeftPart(UriPartial.Authority) + (this.currentContext.Handler as Page).ResolveUrl("~/");
                this.hostLeftPart = this.hostLeftPart.Substring(0, this.hostLeftPart.Length - 1);
                initialized = true;

                ISchedulerFactory schedFact = new StdSchedulerFactory();
                IScheduler sched = schedFact.GetScheduler();
                if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["DisableQuartz"]) && ConfigurationManager.AppSettings["DisableQuartz"].Equals("true", StringComparison.InvariantCultureIgnoreCase)) {
                    if (sched.IsStarted)
                        sched.Shutdown();
                    return;
                }
                if (sched.IsStarted) return;
                sched.Start();
                foreach (QuartzJobSetup item in this.GetSetupJobs()) {
                    if (item.TryGetJobAssemblyType() == null) continue;
                    IJobDetail jobDetails = new JobDetailImpl(item.Name, null, item.TryGetJobAssemblyType());
                    jobDetails.JobDataMap.Add("host", this.hostLeftPart);
                    ITrigger trigger = new CronTriggerImpl(item.Name + "_trigger", null, item.CronTriggerSchedule);
                    sched.ScheduleJob(jobDetails, trigger);
                }

                (sender as HttpApplication).Disposed += app_Disposed;

            }
        }

        void app_Disposed(object sender, EventArgs e) {
            ISchedulerFactory schedFact = new StdSchedulerFactory();
            IScheduler sched = schedFact.GetScheduler();
            if (sched.IsStarted)
                sched.Shutdown(true);
            initialized = false;
        }

        private QuartzJobSetup[] GetSetupJobs() {
            List<QuartzJobSetup> jobs = new List<QuartzJobSetup>();
            DirectoryInfo di = new DirectoryInfo(this.currentServer.MapPath("~/QuartzSetup"));
            if (di.Exists) {
                FileInfo[] files = di.GetFiles("*.config");
                XmlSerializer serializer = new XmlSerializer(typeof(QuartzJobSetup));
                foreach (FileInfo file in files) {
                    using (FileStream fs = file.OpenRead()) {
                        QuartzJobSetup job = serializer.Deserialize(fs) as QuartzJobSetup;
                        if (job != null)
                            jobs.Add(job);
                    }
                }
            }
            return jobs.ToArray();
        }

    }
}